package com.hzhq.contract.service.impl;

import com.hzhq.contract.bean.dto.ContractTypeDTO;
import com.hzhq.contract.bean.dto.UserDTO;
import com.hzhq.contract.bean.entity.ContractType;
import com.hzhq.contract.bean.entity.User;
import com.hzhq.contract.convert.ContractTypeConvertBasic;
import com.hzhq.contract.convert.UserConvertBasic;
import com.hzhq.contract.repo.ContractTypeRepository;
import com.hzhq.contract.service.ContractTypeService;
import com.hzhq.contract.status.DefaultValue;
import com.hzhq.contract.util.Page2ResultUtil;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author: hzhq1255
 * @mail: hzhq1255@163.com
 * @date: 2021/4/18 21:53
 * @desc:
 */
@Service
public class ContractTypeServiceImpl implements ContractTypeService {


    @Autowired
    ContractTypeRepository typeRepo;

    @Autowired
    MongoTemplate mongoTemplate;

    private Boolean isExisted(ObjectId id){
        Optional<ContractType> typeOptional = typeRepo.findByTypeIdAndDeleted(id, DefaultValue.NOT_DELETED);
        return typeOptional.isPresent();
    }

    private Boolean isExisted(String name){
        Optional<ContractType> typeOptional = typeRepo.findByTypeNameAndDeleted(name, DefaultValue.NOT_DELETED);
        return typeOptional.isPresent();
    }

    private Boolean isExisted(Integer code){
        Optional<ContractType> typeOptional = typeRepo.findByTypeCodeAndDeleted(code, DefaultValue.NOT_DELETED);
        return typeOptional.isPresent();
    }

    @Override
    public List<ContractTypeDTO> getAllList() {
        return typeRepo.findByDeleted(DefaultValue.NOT_DELETED).stream().map(ContractTypeConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
    }

    @Override
    public Page<ContractTypeDTO> getAllPage(Integer currentPage, Integer pageSize) {
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize, Sort.by(Sort.Direction.DESC,"id"));
        return typeRepo.findByDeleted(DefaultValue.NOT_DELETED,pageable).map(ContractTypeConvertBasic.INSTANCE::poToDto);
    }

    @Override
    public Page<ContractTypeDTO> searchAllPageByQuery(Query query, Integer currentPage, Integer pageSize) {
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize, Sort.by(Sort.Direction.DESC, ContractType.TYPE_ID_FIELD));
        long count = mongoTemplate.count(query, ContractType.class);
        List<ContractType> contractTypes = mongoTemplate.find(query.with(pageable), ContractType.class);
        List<ContractTypeDTO> contractTypeDTOS  = contractTypes.stream().map(ContractTypeConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
        return new PageImpl<>(contractTypeDTOS, pageable, count);
    }

    @Override
    public ContractTypeDTO getOneById(String id) {
        return typeRepo.findByTypeIdAndDeleted(new ObjectId(id),DefaultValue.NOT_DELETED).map(ContractTypeConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public ContractTypeDTO getOneByName(String name) {
        return typeRepo.findByTypeNameAndDeleted(name,DefaultValue.NOT_DELETED).map(ContractTypeConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public ContractTypeDTO getOneByCode(Integer code) {
        return typeRepo.findByTypeCodeAndDeleted(code,DefaultValue.NOT_DELETED).map(ContractTypeConvertBasic.INSTANCE::poToDto).orElse(null);
    }

    @Override
    public ContractTypeDTO save(ContractTypeDTO contractTypeDTO) {
        List<ContractType> types = typeRepo.findAll(Sort.by(Sort.Direction.DESC,ContractType.TYPE_CODE_FIELD));
        Integer lastCode = types.get(0).getTypeCode();
        ContractType saveType = ContractTypeConvertBasic.INSTANCE.dtoToPo(contractTypeDTO);
        saveType.setTypeCode(lastCode + 1);
        return ContractTypeConvertBasic.INSTANCE.poToDto(typeRepo.save(saveType));
    }

    @Override
    public String deleteById(String id) {
        Optional<ContractType> typeOptional = typeRepo.findByTypeIdAndDeleted(new ObjectId(id), DefaultValue.NOT_DELETED);
        if (typeOptional.isPresent()){
            ContractType contractType = typeOptional.get();
            contractType.setDeleted(DefaultValue.DELETED);
            return typeRepo.save(contractType).getTypeId().toString();
        }
        return null;
    }

    @Override
    public String deleteByName(String name) {
        Optional<ContractType> typeOptional = typeRepo.findByTypeNameAndDeleted(name, DefaultValue.NOT_DELETED);
        if (typeOptional.isPresent()){
            ContractType contractType = typeOptional.get();
            contractType.setDeleted(DefaultValue.DELETED);
            return typeRepo.save(contractType).getTypeId().toString();
        }
        return null;
    }

    @Override
    public String deleteByCode(Integer code) {
        Optional<ContractType> typeOptional = typeRepo.findByTypeCodeAndDeleted(code, DefaultValue.NOT_DELETED);
        if (typeOptional.isPresent()){
            ContractType contractType = typeOptional.get();
            contractType.setDeleted(DefaultValue.DELETED);
            return typeRepo.save(contractType).getTypeId().toString();
        }
        return null;
    }

    @Override
    public Page<ContractTypeDTO> searchAllPages(ContractTypeDTO typeDTO, Integer currentPage, Integer pageSize) {
        ContractType type = ContractTypeConvertBasic.INSTANCE.dtoToPo(typeDTO);
        type.setDeleted(DefaultValue.NOT_DELETED);
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage,pageSize,
                Sort.by(Sort.Direction.DESC,"typeId"));
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("typeName",ExampleMatcher.GenericPropertyMatchers.contains());
        Example<ContractType> typeExample = Example.of(type,exampleMatcher);
        return typeRepo.findAll(typeExample,pageable).map(ContractTypeConvertBasic.INSTANCE::poToDto);
    }
}
